package org.ccay.async;

import java.io.Serializable;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * 异步消息。
 * 每个消息都有一个类型属性，用来标识该消息的类型。
 * 
 * 通常，用户只需要调用setContent来设置消息的主体对象即可；
 * 如果需要传递更多的内容到消息中，可以使用setContext方法。
 * 
 */
public class AsyncMessage implements Serializable {

	/**
	 * 序列号版本号
	 */
	private static final long serialVersionUID = -1202414403892241482L;

	/** 消息的类型 **/
	private String type;

	/** 主内容对象 **/
	private Serializable content;

	/** 上下文相关的对象 **/
	private Map<Class<?>, Serializable> contexts;
	
	/** 附加的上下文 **/
	private Map<String, Serializable> additionalContexts;

	/**
	 * 创建一个异步消息。
	 * 
	 * @param type	消息的类型
	 */
	public AsyncMessage(String type) {
		this.type = type;
	}

	/**
	 * 获取消息的类型。
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @return
	 */
	public String getType() {
		return this.type;
	}

	/**
	 * 设置消息的主体对象，如：XXXVO。
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @param content	一个可序列化的主体对象。
	 */
	public void setContent(Serializable content) {
		this.content = content;
	}

	/**
	 * 获取消息主体。
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @return
	 */
	public Serializable getContent() {
		return this.content;
	}

	/**
	 * 获取上下文相关的对象
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @param <T>
	 * @param format
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T getContext(Class<T> format) {
		return contexts == null ? null : (T)contexts.get(format);
	}

	/**
	 * 设置上下文相关的对象。
	 * 
	 * 
	 * @since Dec 6, 2011
	 * @param <T>
	 * @param format
	 * @param content
	 */
	public <T> void setContext(Class<T> format, Serializable content) {
		if (contexts == null) {
			contexts = new IdentityHashMap<Class<?>, Serializable>(2);
		}
		contexts.put(format, content);
	}
	
	/** 
	 * 获取附加的上下文对象。
	 * 	
	 * 
	 * @since 2012-7-6
	 * @param key
	 * @return
	 */
	public Serializable getAdditionalContext(String key) {
		return additionalContexts==null ? null : additionalContexts.get(key);
	}
	
	/** 
	 * 向附加上下文中设置一个key标识的对象。
	 * 	
	 * 
	 * @since 2012-7-6
	 * @param key
	 * @param context
	 */
	public void setAdditionalContext(String key, Serializable context) {
		if(additionalContexts==null) {
			additionalContexts = new HashMap<String, Serializable>();
		}
		
		additionalContexts.put(key, context);
	}

}
